#ifndef __DALELIB_BONE_H__
#define __DALELIB_BONE_H__

#include <dalelib/graphics.h>
#include <dalelib/maths.h>

namespace dalelib
{


class Bone
{
private:

	Bone* _parent;
	int _num_children;
	int _id;
	v3 _offset; // offset of joint from parent in parent coords
	float _length; // length of bone along local z axis

	m4 _local_mat;
	m4 _local_mat_inv;
	m4 _global_mat;
	m4 _global_mat_inv;
	m4 _global_mat_rest_inv;
	m4 _rest_to_pose_mat;

	v3 _pos;
	v3 _ang;
	v3 _amin, _amax; // angle limits

	string _name;

public:

	Bone(const string _Name,Bone* _Parent,const v3 _Start,const v3 _End,const v3 _Amin=v3(0,0,0),const v3 _Amax=v3(0,0,0));

    string getName() { return _name; }
	v3& getMinAngleLimits() { return _amin; }
	v3& getMaxAngleLimits() { return _amax; }
	m4& getLocalMat() { return _local_mat; }
	m4& getLocalMatInv() { return _local_mat_inv; }
	m4& getGlobalMat() { return _global_mat; }
	m4& getGlobalMatInv() { return _global_mat_inv; }
	m4& getRestToPoseMat() { return _rest_to_pose_mat; }
	void setGlobalMatRestInv() { _global_mat_rest_inv = _global_mat_inv; }
	v3 getBoneEnd() { return _global_mat.getTranslationPart() + _global_mat.z().xyz()*_length; }

	Bone*& getParent() { return _parent; }
	int& getID() { return _id; }
	float& getLength() { return _length; }

	v3 getGlobalPos() { return _global_mat.getTranslationPart(); }
	v3& getPos() { return _pos; }
	v3& getAng() { return _ang; }

	void update();
	void drawUnitBone();
	void draw(const bool _IsCurrent);

};


/*
class Bone
{
private:




	string _name;

	Bone* _parent;
	m4 _local_mat;
	m4 _global_mat;
	m4 _global_mat_inv;
	m4 _global_mat_rest_inv;
	m4 _rest_to_pose_mat;
	v3 _pos;
	v3 _ang;
	int _id;
	bool _is_current;

public:

	Bone(int _ID,Bone* _Parent, const v3 _Pos=v3(0,1,0))
		: _id( _ID )
		, _parent( _Parent )
		, _ang(v3(0,0,0))
		, _is_current(false)
	{
		updateOffset(_Pos);
		update();
	}
	~Bone() { }

	int getID() { return _id; }
	bool& isCurrent() { return _is_current; }
	v3 getGlobalX() {   return v3( _global_mat[ 0], _global_mat[ 1], _global_mat[ 2] ); }
	v3 getGlobalY() {   return v3( _global_mat[ 4], _global_mat[ 5], _global_mat[ 6] ); }
	v3 getGlobalZ() {   return v3( _global_mat[ 8], _global_mat[ 9], _global_mat[10] ); }
	v3 getGlobalPos() { return v3( _global_mat[12], _global_mat[13], _global_mat[14] ); }
	m4& getLocalMat() { return _local_mat; }
	void setLocalPos(const v3 _Pos) { _global_mat[12]=_Pos.x(); _global_mat[13]=_Pos.y(); _global_mat[14]=_Pos.z(); }
	m4& getGlobalMat() { return _global_mat; }
	m4& getGlobalMatInv() { return _global_mat_inv; }
	void setGlobalMatRest() { _global_mat_rest_inv = _global_mat_inv; }
	m4& getRestToPoseMat() { return _rest_to_pose_mat; }
	void updateOffset(const v3 _Pos) { if( _parent ) _pos = _parent->getGlobalMatInv().transformPoint(_Pos); else _pos = _Pos; }

	void update();
	void draw();
	void dump();

};
*/
} // namespace dalelib

#endif
